package org.objectsearch.web.tools;

import java.io.*;
import java.util.*;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.objectsearch.sqlsearch.ObjectSearch;
import org.w3c.dom.*;

import com.alianzamedica.controllers.constants.ActionConstants;

/**
 * @author Carlos
 * 
 */
public class AjaxServlet extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -6199859293998127811L;

	public void init() throws ServletException {
		super.init();
		InputStream in = null;
		InputStream appPropertiesStream = null;
		InputStream documentInputStream = null;
		try {
			ObjectXmlConfigurationEnviroment configurationEnviroment = null;
			configurationEnviroment = ObjectXmlConfigurationEnviroment
					.getInstance();
			String enviromentPath = this.getServletContext().getRealPath("");
			System.out.println("path: " + enviromentPath);
			configurationEnviroment.setEnviromentPath(enviromentPath);
			String oConfigProps = this.getInitParameter("objectNames");
			oConfigProps = enviromentPath + oConfigProps;
			System.out.println("envPath: " + oConfigProps);
			in = new FileInputStream(oConfigProps);
			Properties objectProperties = new Properties();
			objectProperties.load(in);
			objectProperties.list(System.out);
			configurationEnviroment
					.setObjectMappingProperties(objectProperties);
			String appProps = this.getInitParameter("application.properties");
			appProps = enviromentPath + appProps;
			appPropertiesStream = new FileInputStream(appProps);
			Properties envProperties = new Properties();
			envProperties.load(appPropertiesStream);
			envProperties.list(System.out);
			configurationEnviroment.setApplicationProperties(envProperties);
			String objectMappings = this.getInitParameter("database.mappings");
			objectMappings = enviromentPath + objectMappings;
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			documentInputStream = this.loadDocumentInputStream(objectMappings);
			Document document = builder.parse(documentInputStream);
			configurationEnviroment.setObjectMappings(document);
			String connectionImpl = this.getInitParameter("connection.class");
			configurationEnviroment.setConnectionClass(connectionImpl);
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (in != null) {
				try {
					in.close();
				} catch (Exception e) {
				}
			}
			if (appPropertiesStream != null) {
				try {
					appPropertiesStream.close();
				} catch (Exception e) {
				}
			}
			if (documentInputStream != null) {
				try {
					documentInputStream.close();
				} catch (Exception e) {
				}
			}

		}
	}

	private InputStream loadDocumentInputStream(String location) {
		FileInputStream reader = null;
		InputStream in = null;
		try {
			reader = new FileInputStream(location);
			StringBuffer buffer = new StringBuffer();
			int read = 0;
			while ((read = reader.read()) != -1) {
				buffer.append((char) read);
			}
			String xml = buffer.toString();
			String regex = "<!.*>";
			xml = xml.replaceAll(regex, "");
			in = new ByteArrayInputStream(xml.getBytes());
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				reader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return in;
	}

	@SuppressWarnings("unchecked")
	protected void processRequest(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		PrintWriter out = response.getWriter();
		long time1 = System.currentTimeMillis();
		try {
			response.setContentType("text/xml");
			ObjectXmlConfigurationEnviroment enviroment = null;
			enviroment = ObjectXmlConfigurationEnviroment.getInstance();
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder = factory.newDocumentBuilder();
			Document document = docBuilder.newDocument();
			Element root = document.createElement("xml");
			document.appendChild(root);
			String objectType = request.getParameter("objectType");
			if (objectType != null) {
				Properties props = enviroment.getObjectMappingProperties();
				String classForName = props.getProperty(objectType);

				if (classForName != null) {
					try {
						Class _class = Class.forName(classForName);
						Object instance = _class.newInstance();
						ObjectXmlSerializer serializer = new ObjectXmlSerializer(
								document);
						Properties requestProperties = this
								.getPropertiesFromRequest(request);
						serializer.assignProperties2Element(instance,
								requestProperties);
						String connectionImpl = enviroment.getConnectionClass();
						ObjectSearch search = new ObjectSearch(enviroment
								.getObjectMappings(), connectionImpl);
						Integer pageSize = new Integer(ActionConstants.PAGE_SIZE);
						String sPageSize = request.getParameter("pageSize");
						if (sPageSize != null) {
							pageSize = Converter.string2Integer(sPageSize);
						}
						Integer numPage = new Integer(1);
						String sNumPage = request.getParameter("numPage");
						if (sNumPage != null) {
							numPage = Converter.string2Integer(sNumPage);
						}
						if (enviroment.isDebug()) {
							// search.setDebug(true);
						}
						search.setDefaultDialect(ObjectSearch.MYSQL_DIALECT);
						// search.setDefaultDialect( ObjectSearch.ORACLE_DIALECT
						// );
						String sLike = request.getParameter("like");
						if (sLike != null && sLike.equalsIgnoreCase("true")) {
							search.setLike(true);
						}
						String orders[] = request.getParameterValues("order");
						ArrayList list = search.getPagedQuery(instance, orders,
								numPage, pageSize);
						Integer totalPages = search.getTotalPages(instance,
								pageSize);
						Iterator iterator = list.iterator();
						Element dataElement = document.createElement("data");
						root.appendChild(dataElement);
						while (iterator.hasNext()) {
							Object o = (Object) iterator.next();
							Element element = serializer.object2Element(o);
							dataElement.appendChild(element);
						}
						Element infoElement = document.createElement("info");
						root.appendChild(infoElement);
						Element totalPagesElement = document
								.createElement("totalPages");
						Text totalPagesText = document
								.createTextNode(totalPages.toString());
						totalPagesElement.appendChild(totalPagesText);
						infoElement.appendChild(totalPagesElement);
						Element currentPageElement = document
								.createElement("currentPage");
						Text currentPageText = document.createTextNode(numPage
								.toString());
						currentPageElement.appendChild(currentPageText);
						infoElement.appendChild(currentPageElement);
					} catch (Exception ex) {
						Text msg = document.createTextNode(ex.getMessage());
						root.appendChild(msg);
						ex.printStackTrace();
					}
				} else {
					Text msg = document.createTextNode("el objeto no existe");
					root.appendChild(msg);
				}
			} else {
				Text msg = document
						.createTextNode("no se especifico un objeto de busqueda");
				root.appendChild(msg);
			}
			this.printDocument(document, out);
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			try {
				out.close();
			} catch (Exception ex) {
			}
		}
		long time2 = System.currentTimeMillis();
		time2 = time2 - time1;
		System.out.println("tiempo total: " + time2);

	}

	@SuppressWarnings("unchecked")
	private Properties getPropertiesFromRequest(HttpServletRequest request) {
		Properties props = new Properties();
		Enumeration paramNames = request.getParameterNames();
		while (paramNames.hasMoreElements()) {
			String param = (String) paramNames.nextElement();
			String value = request.getParameter(param);
			props.setProperty(param, value);
		}
		return props;
	}

	private void printDocument(Document doc, PrintWriter out)
			throws TransformerException {
		TransformerFactory factory = TransformerFactory.newInstance();
		Transformer transformer = factory.newTransformer();
		Source xmlSource = new DOMSource(doc);
		Result outputTarget = new StreamResult(out);
		transformer.transform(xmlSource, outputTarget);
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		processRequest(req, resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		processRequest(req, resp);
	}

}
